import qiniu from 'qiniu'
import { BadRequest, Conflict } from "http-errors";
import { v4 } from "uuid";
import * as fs from "node:fs";
import multer from 'multer'

// 初始化七牛云配置
qiniu.conf.ACCESS_KEY = process.env.QINIU_ACCESS_KEY
qiniu.conf.SECRET_KEY = process.env.QINIU_SECRET_KEY

const accessKey = process.env.QINIU_ACCESS_KEY
const secretKey = process.env.QINIU_SECRET_KEY
const mac = new qiniu.auth.digest.Mac(accessKey, secretKey)

const bucket = process.env.QINIU_BUCKET


// 空间对应的区域
const config = new qiniu.conf.Config({
  regionsProvider: qiniu.httpc.Region.fromRegionId("z0")
})

const formUploader = new qiniu.form_up.FormUploader(config);
const putExtra = new qiniu.form_up.PutExtra();
const bucketManager = new qiniu.rs.BucketManager(mac, config);

// 设置存储目录
const storage = multer.diskStorage({
  destination: function (_req, _file, cb) {
    cb(null, '');
  },
  filename: function (_req, file, cb) {
    cb(null, file.originalname);
  }
});

const uploadMiddleWare = multer({ storage })

// 封装图片上传函数
async function upload(filePath: string) {
  try {
    // 使用uuid生成唯一的文件名
    const filename = 'upload/' + v4()

    // 第二层过滤：文件路径必须有效
    const isExists = fs.existsSync(filePath)
    if (!isExists) throw new Error("上传的文件路径有误")

    const putPolicy = new qiniu.rs.PutPolicy({
      scope: bucket,
      returnBody: '{"filename":"$(key)"}',
      fsizeLimit: 5 * 1024 * 1024, // 限定上传文件大小最大值为5MB
      mimeLimit: 'image/*'
    });

    const uploadToken = putPolicy.uploadToken(mac); // 生成上传的token，以防过期
    // 文件上传
    const { data, resp } = await formUploader.putFile(uploadToken, filename, filePath, putExtra)

    if (resp.statusCode === 200) {
      const deadline = parseInt(Date.now() / 1000 + '') + 3600; // 1小时过期
      // 上传成功，获取文件url
      const imageUrl = bucketManager.privateDownloadUrl(
        process.env.QINIU_PUBLIC_DOMAIN,
        data.filename,
        deadline
      )
      // 获取文件原始名
      const originalFilename = filePath.slice(filePath.lastIndexOf("/") + 1)

      // 删除保存在本地的图片
      if (fs.existsSync(originalFilename)) {
        fs.unlinkSync(originalFilename)
      }

      // 获取上传文件的信息
      const imageInfo = await bucketManager.stat(bucket, filename)
      return {
        ...imageInfo.data,
        imageUrl,
        originalFilename,
        filename
      }
    } else {
      console.log('data:' + JSON.stringify(data))
      console.log('resp:' + JSON.stringify(resp))
      if (resp.statusCode === 614) {
        throw new Conflict("文件已存在")
      } else if (resp.statusCode === 403) {
        throw new BadRequest("只允许上传图片")
      } else {
        throw new BadRequest("上传失败")
      }
    }
  } catch (error) {
    throw new BadRequest(error.message)
  }
}

// 根据文件名获取文件下载地址
function getFileDownloadUrl(filename: string) {
  const deadline = (parseInt(Date.now() / 1000 + '') + 3600) * 24 * 30; // 30天后过期
  // 上传成功，获取文件url
  return bucketManager.privateDownloadUrl(
    process.env.QINIU_PUBLIC_DOMAIN,
    filename,
    deadline
  )
}

// 封装excel上传函数
async function uploadExcel(filePath: string, userId: string) {
  try {
    const filename = userId + '/' + v4()

    // 第一层过滤：文件后缀必须是xlsx
    if (!filePath.endsWith('.xlsx')) {
      throw new BadRequest("只允许上传xlsx文件")
    }

    // 第二层过滤：文件路径必须有效
    const isExists = fs.existsSync(filePath)
    if (!isExists) throw new Error("上传的文件路径有误")

    const putPolicy = new qiniu.rs.PutPolicy({
      scope: bucket,
      returnBody: '{"filename":"$(key)"}',
      fsizeLimit: 20 * 1024 * 1024, // 限定上传文件大小最大值为20MB
      mimeLimit: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
    });
    const uploadToken = putPolicy.uploadToken(mac); // 生成上传的token，以防过期
    // 文件上传
    const { data, resp } = await formUploader.putFile(uploadToken, filename, filePath, putExtra)

    if (resp.statusCode === 200) {
      const deadline = (parseInt(Date.now() / 1000 + '') + 3600) * 24 * 30; // 30天后过期
      // 上传成功，获取文件url
      const fileUrl = bucketManager.privateDownloadUrl(
        process.env.QINIU_PUBLIC_DOMAIN,
        data.filename,
        deadline
      )
      // 获取文件原始名
      const originalFilename = filePath.slice(filePath.lastIndexOf("/") + 1)

      // 删除保存在本地的文件
      if (fs.existsSync(originalFilename)) {
        fs.unlinkSync(originalFilename)
      }

      // 获取上传文件的信息
      const fileInfo = await bucketManager.stat(bucket, filename)
      return {
        ...fileInfo.data,
        fileUrl,
        originalFilename,
        filename
      }
    } else {
      console.log('data:' + JSON.stringify(data))
      console.log('resp:' + JSON.stringify(resp))
      if (resp.statusCode === 614) {
        throw new Conflict("文件已存在")
      } else {
        throw new BadRequest("上传失败")
      }
    }
  } catch (error) {
    throw new BadRequest(error.message)
  }
}


// 获取示例Excel文件下载地址
function getExampleFileDownloadUrl() {
  try {
    const deadline = parseInt(Date.now() / 1000 + '') + 3600; // 1小时过期
    return bucketManager.privateDownloadUrl(
      process.env.QINIU_PUBLIC_DOMAIN,
      'example.xlsx',
      deadline
    )
  } catch (error) {
    throw new BadRequest(error.message)
  }
}

export { upload, uploadMiddleWare, getFileDownloadUrl, getExampleFileDownloadUrl, uploadExcel }